package com.huiquan.vocab.service;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.vocab.dao.VocabElementLabelDao;
import com.huiquan.vocab.domain.VocabElementLabel;
import com.huiquan.vocab.domain.VocabElementLabelResult;
import com.huiquan.vocab.domain.VocabElementLabelResultDto;
import com.huiquan.vocab.domain.VocabElementLabelWord;

@Service
public class VocabElementLabelService extends BaseService {

	@Autowired
	private VocabElementLabelDao vocabElementLabelDao;

	public ModelAndView list(String startStr, String elementKey, String exactSearchFlag, String checkFlag,
			String labelKey,String countPerPageStr) {

		Map<String, Object> param = new HashMap<>();
		if (elementKey != null && !elementKey.isEmpty()) {
			if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
				param.put("element", elementKey);
			} else {
				param.put("element", "%" + elementKey + "%");
			}
		}
		if (checkFlag != null && !checkFlag.isEmpty()) {
			param.put("checkFlag", checkFlag);
		}
		if (labelKey != null && !labelKey.isEmpty()) {
			param.put("label", labelKey);
		}
		int totalSize = vocabElementLabelDao.retrieveResultSize(param);

		Map<String, Integer> pageNo ;
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			int countPerPage = Integer.parseInt(countPerPageStr);
			pageNo = GetListUtil.getPageNoParam(totalSize, startStr, countPerPage);
			param.put("countPerPage", countPerPage);
		} else {
			pageNo = GetListUtil.getPageNoParam(totalSize, startStr);
		}
		int endPage = pageNo.get("endPage");
		int start = pageNo.get("start");
		int startIndex = pageNo.get("startIndex");

		List<VocabElementLabelResultDto> list = new ArrayList<>();

		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			param.put("orderStr", "rank");
			list = vocabElementLabelDao.retrieveResultList(param);

			for (VocabElementLabelResultDto result : list) {
				List<String> labelResultList = result.getLabelResultList();
				if (labelResultList == null) {
					labelResultList = new ArrayList<>();
					result.setLabelResultList(labelResultList);
				}

				String label = result.getLabel();
				if (label != null && !label.isEmpty()) {
					for (String temp : label.split(",")) {
						if (!temp.isEmpty()) {
							labelResultList.add(temp);
						}
					}
				}
			}
		}

		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("elementKey", "词语");

		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, null);
		map.put("showSearch", showSearch);
		map.put("checkFlag", checkFlag);
		// 返回标签列表
		map.put("labelList", getLabelList());

		return new ModelAndView("vocab/element_index", map);
	}

	private List<String> getLabelList() {

		List<String> labelList = new ArrayList<>();
		for (VocabElementLabel o : vocabElementLabelDao.retrieveList()) {
			labelList.add(o.getLabel());
		}

		return labelList;
	}

	public void init() {
		vocabElementLabelDao.init();
	}

	public ReturnData addLabel(String label) {
		// 判断是否重复
		VocabElementLabel labelObj = vocabElementLabelDao.retrieveByLabel(label);
		if (labelObj != null) {
			return ReturnUtil.fail(ReturnCode.ELEMENT_CATEGORY_NAME_REPEAT);
		}

		// 维护添加标签
		labelObj = new VocabElementLabel();
		labelObj.setLabel(label);

		vocabElementLabelDao.insert(labelObj);

		return ReturnUtil.success();
	}

	public ReturnData changeLabel(String id, String label) {

		VocabElementLabelResult labelObj = vocabElementLabelDao.retrieveResultById(Long.parseLong(id));
		labelObj.setLabel(label);

		vocabElementLabelDao.updateResult(labelObj);

		return ReturnUtil.success();
	}

	public ReturnData changeQuantization(String id, String quantization) {

		VocabElementLabelResult labelObj = vocabElementLabelDao.retrieveResultById(Long.parseLong(id));
		labelObj.setQuantization(quantization);

		vocabElementLabelDao.updateResult(labelObj);

		return ReturnUtil.success();
	}

	public List<List<String>> initLabelLists() {
		List<String> labelList = vocabElementLabelDao.retrieveLabelByParent("");

		List<List<String>> labelLists = new ArrayList<>();
		labelLists.add(labelList);

		return labelLists;
	}

	public List<List<String>> getLabelListsByKey(List<List<String>> labelLists, String labelKey) {
		if (labelKey.isEmpty()) {
			labelLists = labelLists.subList(0, 1);
		} else {
			for (int i = 0; i < labelLists.size(); i++) {
				if (labelLists.get(i).contains(labelKey)) {
					labelLists = labelLists.subList(0, i + 1);
					break;
				}
			}

			List<String> labelList = vocabElementLabelDao.retrieveLabelByParent(labelKey);
			if (!labelList.isEmpty()) {
				labelLists.add(labelList);
			}
		}

		return labelLists;
	}

	public void labelExport(HttpServletResponse resp) throws Exception {
		RespHeaderUtil.setXlsxResp(resp, "标签");

		Workbook workbook = new XSSFWorkbook(); // 创建文档

		// 根据property和keyword获取同义词列表
		Map<String, Object> param = new HashMap<>();
		param.put("orderStr", "rank");
		List<VocabElementLabelResultDto> vocabElementResultList = vocabElementLabelDao.retrieveResultList(param);

		Sheet sheet = workbook.createSheet(); // 创建Sheet
		Cell cell = null;
		for (int i = 0; i < vocabElementResultList.size(); i++) {
			VocabElementLabelResultDto result = vocabElementResultList.get(i);

			Row row = sheet.createRow(i);
			cell = row.createCell(0);
			cell.setCellValue(result.getElement());

			String[] labelArray = result.getLabel().split(",");
			int cellNum = 0;
			for (int j = 0; j < labelArray.length; j++) {
				if (!labelArray[j].trim().isEmpty()) {
					cell = row.createCell(++cellNum);
					cell.setCellValue(labelArray[j].trim());
				}
			}

			if (!result.getQuantization().trim().isEmpty()) {
				cell = row.createCell(++cellNum);
				cell.setCellValue(result.getQuantization().trim());
			}
			if(StringUtils.isNotBlank(result.getIsDecorateO())){
				cell = row.createCell(++cellNum);
				cell.setCellValue(result.getIsDecorateO().trim());
			}
		}

		OutputStream os = resp.getOutputStream();
		workbook.write(os);

		os.close();
		workbook.close();
	}

	/**
	 * 标签导入：第一列为小词，最后一列是量化，中间为标签；小词是系统中待标签小词，且必有标签；量化以阿拉伯数字开头，可空；
	 * 标签不能以阿拉伯数字开头不能有两个不同的上级；
	 * 
	 * @param file
	 * @return
	 * @throws Exception
	 */
	public ReturnData labelImport(MultipartFile file) throws Exception {

		// 获取待标签词语
		List<VocabElementLabelWord> wordList = vocabElementLabelDao.retrieveWordList();
		Map<String, Long> wordIdMap = new HashMap<>();
		for (VocabElementLabelWord word : wordList) {
			wordIdMap.put(word.getElement(), word.getId());
		}

		// 获取文件流，解析文件
		InputStream inputStream = file.getInputStream();

		Workbook workbook = new XSSFWorkbook(inputStream);
		Sheet sheet = workbook.getSheetAt(0);

		Map<String, String> labelParent = new HashMap<>();
		List<String> elementLabel = new ArrayList<>();
		List<VocabElementLabelResultDto> resultList = new ArrayList<>();

		StringBuffer elementErr = new StringBuffer();
		StringBuffer labelErr = new StringBuffer();
		StringBuffer parentErr = new StringBuffer();
		StringBuffer elementLabelErr = new StringBuffer();
		StringBuffer isDecorateOErr = new StringBuffer();
		StringBuffer label;
		Map<String, String> elementO = new HashMap<>();
		VocabElementLabelResultDto result;
		String cellString, parent, elementLabelStr;
		Long wordId;
		int rank = 1;
		int rowNum = 1;
		for (Row row : sheet) {
			//获取列数
			int colCount = row.getPhysicalNumberOfCells();
			result = new VocabElementLabelResultDto();
			label = new StringBuffer();
			parent = "";

			int i = 0;
			//小词
			String	element = "";
			for (Cell cell : row) {
				cell.setCellType(Cell.CELL_TYPE_STRING);
				cellString = cell.getStringCellValue().trim();
				if (i == 0) {
					// 如果是空则跳过这一行
					if (cellString.isEmpty()) {
						break;
					}
					element = cellString;
					// 第一列数据为小词，必须在小词列表中
					wordId = wordIdMap.get(cellString);
					if (wordId == null) {
						elementErr.append(cellString);
						elementErr.append(",");
					}
					result.setElement(cellString);
					result.setWord(cellString);
				} else {
					if(i == colCount-1){
						if(StringUtils.equals("1", cellString) || StringUtils.equals("0", cellString)){
							//最后行是否修饰o
							//判断每一个小词的是否修饰o属性是否一致
							result.setIsDecorateO(cellString);
							elementO.put(element, cellString);
						}else{
							isDecorateOErr.append(rowNum);
							isDecorateOErr.append(",");
						}
					}else if (Pattern.matches("^\\d.*", cellString)) {
						// 如果是阿拉伯数字开头则为量化
						result.setQuantization(cellString);
					} else {
						// 标签
						label.append(cellString);
						label.append(",");

						// 标签不能有两个上级标签
						if (labelParent.get(cellString) != null && !parent.equals(labelParent.get(cellString))) {
							parentErr.append(cellString);
						} else {
							labelParent.put(cellString, parent);
						}
						parent = cellString;
					}

					if (i == 1) {
						// 小词对应第一个标签不能有重复的
						elementLabelStr = result.getElement() + "-" + cellString;
						if (elementLabel.contains(elementLabelStr)) {
							elementLabelErr.append(result.getElement());
							elementLabelErr.append(",");
						}
					}
				}
				i++;
			}
			rowNum++;

			// 如果没有小词则跳过这一行
			if (result.getElement() == null || result.getElement().isEmpty()) {
				continue;
			}
			if (label.length() == 0) {
				// 如果没有标签则提示
				labelErr.append(result.getElement());
				labelErr.append(",");
			} else {
				label.insert(0, ",");
				result.setLabel(label.toString());
				result.setRank(rank++);
				if (result.getQuantization() == null) {
					result.setQuantization("");
				}
				resultList.add(result);
			}
		}

		workbook.close();
		inputStream.close();

		StringBuffer err = new StringBuffer();
		if (elementErr.length() > 0) {
			err.append("以下小词不在待标签列表中：");
			err.append(elementErr);
		}
		if (labelErr.length() > 0) {
			err.append("以下小词没有标签：");
			err.append(labelErr);
		}
		if (parentErr.length() > 0) {
			err.append("以下标签有多个上级：");
			err.append(parentErr);
		}
		if (elementLabelErr.length() > 0) {
			err.append("以下小词有相同的一级标签：");
			err.append(elementLabelErr);
		}
		if (isDecorateOErr.length() > 0) {
			err.append("以下行是否修饰o填写有误：");
			err.append(isDecorateOErr);
		}
		if (err.length() > 0) {
			ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
			rc.setDesc(err.toString());
			return ReturnUtil.fail(rc);
		}

		// 批量删除标签和结果后重新批量添加
		List<VocabElementLabel> labelList = new ArrayList<>();
		for (String temp : labelParent.keySet()) {
			VocabElementLabel o = new VocabElementLabel();
			o.setLabel(temp);
			o.setParent(labelParent.get(temp));
			labelList.add(o);
		}

		vocabElementLabelDao.deleteAll();
		vocabElementLabelDao.deleteAllResult();

		vocabElementLabelDao.batchInsert(labelList);
		vocabElementLabelDao.batchInsertResult(resultList);

		return ReturnUtil.success();
	}
	
	public ReturnData changeisDecorateO(String id,String isDecorateO) throws Exception {
		if(StringUtils.isNotBlank(id) && StringUtils.isNotBlank(isDecorateO)){
			vocabElementLabelDao.updateIsDecorateO(id, isDecorateO);
		}
		return ReturnUtil.success();
	}
}
